perm filename TEST.TEX[WEB,ALS]3 blob sn#673721 filedate 1982-08-27 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00002 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	\def\TEX{\hbox{T\hskip-.125em\lower.5ex\hbox{E}\hskip-.075em X}}
C00015 ENDMK
C⊗;
\def\TEX{\hbox{T\hskip-.125em\lower.5ex\hbox{E}\hskip-.075em X}}
A simple radical.
$$\sqrt{1+\sqrt{2+\sqrt{3+\sqrt{4+\sqrt{5+x}}}}}$$

\vfill
\end

GENTLE READER: This is a handbook about
\TEX, a new typesetting system intended for the creation
of beautiful books---and especially for books that contain a lot of
mathematics. By preparing a manuscript in \TEX\ format, you will be
telling a computer exactly how the manuscript is to be transformed into
pages whose typographic quality is comparable to that of the world's
finest printers; yet you won't need to do much more work than would be
involved if you were simply typing the manuscript on an ordinary
typewriter. In fact, your total work will probably be significantly less,
if you consider the time it ordinarily takes to revise a typewritten manuscript,
since computer text files are so easy to change and to reprocess.\quad
(If such claims sound too good to be true, keep in mind that they were made
by \TEX's designer, on a day when \TEX\ happened to
be working, so the statements may be biased; but read on anyway.)

@ The |var_delimiter| function, which finds or constructs a sufficiently
large delimiter, is the most interesting of the auxiliary functions that
currently concern us. Given a pointer |d| to a delimiter field in some noad,
together with a size code |s| and a vertical distance |v|, this function
returns a pointer to a box that contains the smallest variant of |d| whose
height plus depth is |v| or more. (And if no variant is large enough, it
returns the largest available variant.) In particular, this routine will
construct arbitrarily large delimiters from extensible components, if
|d| leads to such characters.

The value returned is a box whose |shift_amount| has been set so that
the box is vertically centered with respect to the axis in the given size.
If a built-up symbol is returned, the height of the box before shifting
will be the height of its topmost component.

@p@t\4@>@<Declare subprocedures for |var_delimiter|@>
function var_delimiter(@!d:pointer;@!s:small_number;@!v:scaled):pointer;
label found,continue;
var b:pointer; {the box that will be constructed}
@!f,@!g: internal_font_number; {best-so-far and tentative font codes}
@!c,@!x,@!y: quarterword; {best-so-far and tentative character codes}
@!m,@!n: integer; {the number of extensible pieces}
@!u: scaled; {height-plus-depth of a tentative character}
@!w: scaled; {largest height-plus-depth so far}
@!q: four_quarters; {character info}
@!hd: eight_bits; {height-depth byte}
@!r: four_quarters; {extensible pieces}
@!p: pointer; {character nodes constructed}
@!z: small_number; {runs through font family members}
@!large_attempt: boolean; {are we trying the ``large'' variant?}
begin f←undefined_font; w←0; large_attempt←false;
z←small_fam(d); x←small_char(d);
loop@+	begin @<Look at the variants of |(z,x)|; set |f| and |c| whenever
		a better character is found; |goto found| as soon as a
		large enough variant is encountered@>;
	if large_attempt then goto found; {there were none large enough}
	large_attempt←true; z←large_fam(d); x←large_char(d);
	end;
found: if f≠undefined_font then
	@<Make variable |b| point to a box for |(f,c)|@>
else	begin b←new_null_box;
	width(b)←null_delimiter_space; {use this width if no delimiter was found}
	end;
shift_amount(b)←half(height(b)-depth(b)) - axis_height(s);
var_delimiter←b;
end;

@ The search process is complicated slightly by the facts that some of the
characters might not be present in some of the fonts, and they might not
be probed in increasing order of height.

@<Look at the variants of |(z,x)|; set |f| and |c|...@>=
if (z≠0)∨(x≠min_quarterword) then
	begin z←z+s+16;
	repeat z←z-16; g←fam_fnt(z);
	if g≠undefined_font then
		@<Look at the list of characters starting with |x| in
			font |g|; set |f| and |c| whenever
			a better character is found; |goto found| as soon as a
			large enough variant is encountered@>;
	until z<16;
	end

@ @<Look at the list of characters starting with |x|...@>=
begin y←x;
continue: if (qo(y)≥font_bc[g])∧(qo(y)≤font_ec[g]) then
	begin q←char_info(g)(y);
	if char_exists(q) then
		begin if char_tag(q)=ext_tag then
			begin f←g; c←y; goto found;
			end;
		hd←height_depth(q);
		u←char_height(g)(hd)+char_depth(g)(hd);
		if u>w then
			begin f←g; c←y; w←u;
			if u≥v then goto found;
			end;	
		if char_tag(q)=list_tag then
			begin y←rem_byte(q); goto continue;
			end;
		end;
	end;
end

@ Here is a subroutine that creates a new box, whose contents is a
single character, and whose width includes the italic correction for
that character. The height or depth of the box will be negative, if
the height or depth of the character is negative; thus, this routine
may deliver a slightly different result than |hpack| would produce.

@<Declare subprocedures for |var_delimiter|@>=
function char_box(@!f:internal_font_number;@!c:quarterword):pointer;
var q:four_quarters;
@!hd:eight_bits; {|height_depth| byte}
@!b,@!p:pointer; {the new box and its character node}
begin q←char_info(f)(c); hd←height_depth(q);
b←new_null_box; width(b)←char_width(f)(q)+char_italic(f)(q);
height(b)←char_height(f)(hd); depth(b)←char_height(f)(hd);
p←get_avail; character(p)←c; font(p)←f; list_ptr(b)←p; char_box←b;
end;

@ When the following code is executed, |char_tag(q)| will be equal to
|ext_tag| if and only if a built-up symbol is supposed to be returned.

@<Make variable |b| point to a box for |(f,c)|@>=
if char_tag(q)=ext_tag then
	@<Construct an extensible character in a new box |b|,
		using recipe |rem_byte(q)| and font |f|@>
else b←char_box(f,c)

@ When we build an extensible character, it's handy to have the
following subroutine, which puts a given character on top
of the characters already in box |b|:

@<Declare subprocedures for |var_delimiter|@>=
procedure stack_into_box(@!b:pointer;@!f:internal_font_number;
	@!c:quarterword);
var p:pointer; {new node placed into |b|}
begin p←char_box(f,c); link(p)←list_ptr(b); list_ptr(b)←p;
height(b)←height(p);
end;

@ Another handy subroutine computes the height plus depth of
a given character:

@<Declare subprocedures for |var_delimiter|@>=
function height_plus_depth(@!f:internal_font_number;@!c:quarterword):scaled;
var q:four_quarters;
@!hd:eight_bits; {|height_depth| byte}
begin q←char_info(f)(c); hd←height_depth(q);
height_plus_depth←char_height(f)(hd)+char_depth(f)(hd);
end;

@ @<Construct an extensible...@>=
begin b←new_null_box;
type(b)←vlist_node;
r←font_info[exten_base[f]+rem_byte(q)].qqqq;@/
@<Compute the minimum suitable height, |w|, and the corresponding
	number of extension steps, |n|; also set |width(b)|@>;
c←ext_bot(r);
if c≠min_quarterword then stack_into_box(b,f,c);
c←ext_rep(r);
for m←1 to n do stack_into_box(b,f,c);
c←ext_mid(r);
if c≠min_quarterword then
	begin stack_into_box(b,f,c); c←ext_rep(r);
	for m←1 to n do stack_into_box(b,f,c);
	end;
c←ext_top(r);
if c≠min_quarterword then stack_into_box(b,f,c);
depth(b)←w-height(b);
end

@ The width of an extensible character is the width of the repeatable
mod\-ule. If this module does not have positive height plus depth,
we don't use any copies of it, otherwise we use as few as possible
(in groups of two if there is a middle part).

@<Compute the minimum suitable height, |w|, and...@>=
c←ext_rep(r); u←height_plus_depth(f,c);
w←0; q←char_info(f)(c); width(b)←char_width(f)(q)+char_italic(f)(q);@/
c←ext_bot(r);@+if c≠min_quarterword then w←w+height_plus_depth(f,c);
c←ext_mid(r);@+if c≠min_quarterword then w←w+height_plus_depth(f,c);
c←ext_top(r);@+if c≠min_quarterword then w←w+height_plus_depth(f,c);
n←0;
if u>0 then while w<v do
	begin w←w+u; incr(n);
	if ext_mid(r)≠min_quarterword then w←w+u;
	end